import math
import random

import numpy as np
import pandas as pd

import pydirectinput as pdg
import pyautogui as pag


def cal_angle(line1, line2):
    # 计算两条直线的斜率
    vector_AB = [line1[1][0] - line1[0][0], line1[1][1] - line1[0][1]]
    vector_CD = [line2[1][0] - line2[0][0], line2[1][1] - line2[0][1]]

    # 计算向量AB和向量CD的点积
    dot_product = vector_AB[0] * vector_CD[0] + vector_AB[1] * vector_CD[1]

    # 计算向量AB和向量CD的模
    magnitude_AB = math.sqrt(vector_AB[0] ** 2 + vector_AB[1] ** 2)
    magnitude_CD = math.sqrt(vector_CD[0] ** 2 + vector_CD[1] ** 2)

    # 计算夹角的弧度
    angle_rad = math.acos(dot_product / (magnitude_AB * magnitude_CD))

    # 将弧度转换为角度
    angle_degrees = math.degrees(angle_rad)

    return angle_degrees


def cal_move_point(point, target_point, unit_d=6):
    Xp, Yp = point
    Xt, Yt = target_point
    # print("(Xp - Xt)^2:", (Xp - Xt)**2)
    distance = math.sqrt((Xp - Xt) ** 2 + (Yp - Yt) ** 2)
    print("distance:", distance)
    ratio = unit_d / distance
    Xe = Xp + ratio * (Xt - Xp)
    Ye = Yp + ratio * (Yt - Yp)
    return (Xe, Ye)


def get_euclidean_distance(point1, point2):
    distance = math.sqrt((point1[0] - point2[0]) ** 2 + (point1[1] - point2[1]) ** 2)
    return distance


def check_in_range(point, target_point, criterion=3):
    distance = get_euclidean_distance(point, target_point)
    print("distance:", distance)
    if distance <= criterion:
        return True
    else:
        return False


def get_rotation_angle(line1, line2):
    angle = cal_angle(line1, line2)
    rotation_angle = 180 - angle
    return rotation_angle


class OneMove:

    def __init__(self, start_point, end_point, unit_distance=6):
        self.current_point = start_point
        self.end_point = end_point
        self.unit_distance = unit_distance
        self.previous_point = None
        self.track = [start_point]
        self.unit_pixel = self.unit_distance * 32
        self.person_position = (int(1280 / 2), int(960 / 2))
        self.fixed_move_position = self.person_position[0] + self.unit_pixel

    def step(self):
        # Sx, Sy = pdg.position()
        pdg.click()
        self.current_point = (self.current_point[0] + 5, self.current_point[1] + 3)
        # 650 + 150 = 800 -> 650
    def run(self):
        self.step()
        return self.current_point


class Schedule:

    def __init__(self, plan_file=None, end_point=None, unit_distance=6):
        df = pd.read_excel("data/coor.xlsx", sheet_name="plan")
        self.plan = [(X, Y) for X, Y in df[["X", "Y"]].values]
        self.unit_distance = unit_distance
        self.end_point = end_point
        self.current_plan_index = None
        self.max_index = len(self.plan) - 1

    def detect_current_point(self):
        start_point_x = random.randint(100, 800)
        start_point_y = random.randint(100, 800)
        # start_point = (start_point_x, start_point_y)
        return (start_point_x, start_point_y)

    def get_nearest_plan_point(self, point):
        distances = [get_euclidean_distance(point, point_in_plan) for point_in_plan in self.plan]
        index = np.argmin(distances)
        return (index, self.plan[index])

    def get_next_plan_point(self):
        if self.current_plan_index is not None:
            if self.current_plan_index < self.max_index:
                self.current_plan_index += 1
            else:
                self.current_plan_index = 0
        return self.plan[self.current_plan_index]

    def run(self):
        current_point = self.detect_current_point()
        self.current_plan_index, nearest_plan_point = self.get_nearest_plan_point(current_point)
        while True:
            mover = OneMove(current_point, nearest_plan_point, unit_distance=self.unit_distance)
            current_point = mover.run()
            if self.end_point is not None:
                if check_in_range(current_point, self.end_point, criterion=self.unit_distance):
                    break
            else:
                nearest_plan_point = self.get_next_plan_point()
            break


#
# def move(start_point, target_point, plan, unit_d=6):
#     trajectory = [start_point]
#     # 要求：沿着既定路线，走到目标点
#     # 参数设定：
#     # - 标准移动距离：6
#     # - 找到的标准：移动都6单位以内
#     # 1.求起始点到所有目标点的距离，找到距离最近的点
#     nearest_index, nearest_plan_point = get_nearest_plan_point(start_point, plan)
#     print("最近计划点：", nearest_plan_point)
#     # 2.计算转向角度；因为你不直到当前视角朝向；
#     # 随机走一步，但这一步不在nearest_plan_point和target_point的连线上
#     previous_point = start_point
#     current_point = (start_point[0] + 5, start_point[1] + 3)
#     trajectory.append(current_point)
#     line1 = [current_point, previous_point]
#     line2 = [current_point, nearest_plan_point]
#     rotation_angle = get_rotation_angle(line1, line2)
#     print("转动角度：", rotation_angle)
#     # 3.移动最小距离；
#     tmp_point = current_point
#     current_point = cal_move_point(tmp_point, nearest_plan_point, unit_d=unit_d)
#     previous_point = tmp_point
#
#     # 4.重复2和3，直到到达最近的点；
#     if not check_in_range(current_point, nearest_plan_point, criterion=3):
#         # 重复
#         pass
#     else:
#         nearest_index += 1
#         nearest_plan_point = plan[nearest_index]


# 5.选择与目标点距离最近的规划点，重复2到4，直到到达目标点


if __name__ == "__main__":
    pass
    # start_point_x = random.randint(100, 800)
    # start_point_y = random.randint(100, 800)
    # target_point = (680, 580)
    # start_point = (start_point_x, start_point_y)
    # df = pd.read_excel("data/coor.xlsx", sheet_name="plan")
    # print(df.head())
    # plan = [(X, Y) for X, Y in df[["X", "Y"]].values]
    # print("start_point:", start_point)
    #
    # move(start_point, target_point, plan)
